import { type MouseEvent, useContext, useEffect, useState } from 'react';
import type {
  IPostCommentChildReply,
  IPostCommentParentReply,
  IPostCommentReply,
  IUserOv,
} from '@/interfaces';
import Link from 'next/link';
import Image from 'next/image';
import classNames from 'classnames';
import { getUserAvatar, toRelativeTime } from '@/lib/tool';
import useOffcanvas from 'hooks/useOffcanvas';
import ChildReplyPostIdH5Page from '@/app/[locale]/mobile/posts/[id]/childReply';
import { useInfiniteQuery } from '@tanstack/react-query';
import { queryAllParentReplyByReplyId } from '@/services/api';
import LoadMoreBtn from '@/app/[locale]/mobile/posts/[id]/loadMoreBtn';
import useToast from 'hooks/useToast';
import ChildReplyBtnPostIdH5Page from '@/app/[locale]/mobile/posts/[id]/childReplyBtn';
import ContentHtml from '@/app/[locale]/common/content/html';
import { AppContext } from '@/contexts/app';
import { PostIdPageContext } from '@/contexts/post-id';

export default function ParentReplyPostIdH5Page({
  itemData,
}: {
  itemData: IPostCommentReply;
}) {
  const context = useContext(PostIdPageContext)!;
  const [pages, setPages] = useState<IPostCommentParentReply[]>(
    itemData.content,
  );
  const { show } = useToast();
  const queryKey = [
    '/forum',
    '/replies',
    itemData.reply.id,
    '/parent',
    'infinite',
  ];

  const replyQuery = useInfiniteQuery(
    queryKey,
    async (context) => {
      return (await queryAllParentReplyByReplyId({
        id: context.queryKey[2],
        query: context.pageParam,
      })) as IPostCommentReply;
    },
    {
      keepPreviousData: true,
      getPreviousPageParam: (firstPage) => {
        if (!firstPage.pageable.previous) {
          return;
        }
        return {
          page: Math.max(firstPage.pageable.page - 1, 0),
        };
      },
      getNextPageParam: (lastPage) => {
        if (!lastPage.pageable.next) {
          return;
        }
        return {
          page: Math.min(lastPage.pageable.page + 1, lastPage.pageable.pages),
        };
      },
      initialData: () => {
        return {
          pages: [itemData],
          pageParams: [{ page: 0 }],
        };
      },
    },
  );

  useEffect(() => {
    if (replyQuery.data) {
      setPages(
        replyQuery.data.pages
          .flatMap((item) => item.content)
          .map((item) => {
            item.reply._createdOnText = toRelativeTime(item.reply.createdOn);
            item.content.forEach((value) => {
              value.reply._createdOnText = toRelativeTime(
                value.reply.createdOn,
              );
            });
            return item;
          }),
      );
    }
  }, [replyQuery.data]);

  async function onClickLoadMore() {
    try {
      await replyQuery.fetchNextPage();
    } catch (e) {
      show({
        type: 'DANGER',
        message: e,
      });
    }
  }

  return (
    <PostIdPageContext.Provider value={{ ...context, queryKey }}>
      <div className="vstack gap-4">
        {pages.map((item, index) => {
          return (
            <Item
              key={item.reply.id}
              index={index}
              id={item.reply.id}
              content={item.reply.content}
              user={item.user}
              createdOn={item.reply.createdOn}
              _createdOnText={item.reply._createdOnText}
              items={item.content}
              itemData={item}
            />
          );
        })}

        <LoadMoreBtn
          isLoading={replyQuery.isFetchingNextPage}
          onClickLoadMore={onClickLoadMore}
        />

        <div></div>
      </div>
    </PostIdPageContext.Provider>
  );
}

const Item = ({
  id,
  content,
  index,
  user,
  createdOn,
  _createdOnText,
  items,
  itemData,
}: {
  id: number;
  content: string;
  index: number;
  user: IUserOv;
  createdOn: string;
  _createdOnText: string | undefined;
  items: IPostCommentChildReply[];
  itemData: IPostCommentParentReply;
}) => {
  return (
    <div className="vstack gap-2">
      <Name
        id={id}
        createdOn={createdOn}
        _createdOnText={_createdOnText}
        user={user}
        left={index % 2 === 0}
      />
      <Content id={id} items={items} content={content} itemData={itemData} />
    </div>
  );
};

const Name = ({
  id,
  createdOn,
  _createdOnText,
  user,
  left = true,
  width = 56,
  height = 56,
  bgColor = 'bg-white',
  stickyTop = false,
}: {
  id: number;
  createdOn: string;
  _createdOnText: string | undefined;
  user: IUserOv;
  left?: boolean;
  width?: number;
  height?: number;
  bgColor?: string;
  stickyTop?: boolean;
}) => {
  const context = useContext(AppContext);
  const metadata = context.metadata!;
  const env = metadata.env;

  return (
    <div
      className={classNames(
        'hstack gap-4 py-2 pb-3',
        {
          'sticky-top': stickyTop,
        },
        bgColor ? bgColor : false,
      )}
    >
      <div
        className={classNames(
          'hstack gap-4 justify-content-between align-items-center flex-grow-1',
          {
            'flex-row-reverse': !left,
          },
        )}
      >
        <div
          className={classNames('hstack gap-4 align-items-center', {
            'flex-row-reverse': !left,
          })}
        >
          <div className="flex-shrink-0">
            <Link
              href={`/users/${user.id}`}
              className="link-body-emphasis link-offset-3 link-underline-opacity-0 link-underline-opacity-100-hover"
            >
              <Image
                className="rounded-4"
                src={getUserAvatar(user, metadata).mediumAvatarUrl}
                alt="avatar"
                width={width}
                height={height}
                placeholder="blur"
                blurDataURL={env.APP_BLUR_DATA_URL}
              />
            </Link>
          </div>
          <div
            className={classNames('flex-grow-1 vstack gap-2', {
              'text-end': !left,
            })}
          >
            <Link
              href={`/users/${user.id}`}
              className="link-body-emphasis link-offset-3 link-underline-opacity-0 link-underline-opacity-100-hover"
            >
              {user.alias}
            </Link>
            <time dateTime={createdOn} className="text-secondary small">
              {_createdOnText}
            </time>
          </div>
        </div>
        <ChildReplyBtnPostIdH5Page id={id} alias={user.alias} />
      </div>
    </div>
  );
};

const Content = ({
  id,
  content,
  items,
  itemData,
}: {
  id: number;
  content: string;
  items: IPostCommentChildReply[];
  itemData: IPostCommentParentReply;
}) => {
  return (
    <div className="border rounded-4 bg-light-subtle vstack gap-3 p-3 overflow-hidden">
      <div className="vstack gap-3 justify-content-center">
        <ContentHtml content={content} />
        {items.length > 0 && (
          <div className="vstack gap-4">
            <ChildReplyContent id={id} items={items} />
            <ViewMoreReplies itemData={itemData} />
          </div>
        )}
      </div>
    </div>
  );
};

const ChildReplyContent = ({
  id,
  items,
}: {
  id: number;
  items: IPostCommentChildReply[];
}) => {
  return (
    <div className="vstack gap-2 border rounded-4 bg-light-subtle p-3">
      {items.map((item, index) => {
        return (
          <div key={item.reply.id}>
            <Name
              id={id}
              width={48}
              height={48}
              createdOn={item.reply.createdOn}
              _createdOnText={item.reply._createdOnText}
              user={item.user}
              left={index % 2 === 0}
              bgColor=""
              stickyTop={false}
            />
            <ContentHtml
              classs={classNames({
                'text-end': index % 2 !== 0,
              })}
              content={item.reply.content}
            />
          </div>
        );
      })}
    </div>
  );
};

const ViewMoreReplies = ({
  itemData,
}: {
  itemData: IPostCommentParentReply;
}) => {
  const context = useContext(PostIdPageContext)!;
  const { translatedFields } = context;
  const { isLoadingOffcanvasShowing, showOffcanvas } = useOffcanvas();
  const [isLoading, setLoading] = useState(false);

  useEffect(() => {
    setLoading(isLoadingOffcanvasShowing);
  }, [isLoadingOffcanvasShowing]);

  function onClickSeeMore(e: MouseEvent<HTMLAnchorElement>) {
    e.stopPropagation();
    e.preventDefault();

    if (isLoading) {
      return;
    }

    showOffcanvas({
      title: `@${itemData.user.alias}`,
      bottom: true,
      content: (
        <PostIdPageContext.Provider value={context}>
          <ChildReplyPostIdH5Page itemData={itemData} />
        </PostIdPageContext.Provider>
      ),
      offcanvasBodyClass: 'pt-0',
      backdrop: false,
      offcanvasStyle: {
        height: '85vh',
      },
    });
  }

  return (
    <div className="small">
      <a
        onClick={onClickSeeMore}
        className="text-decoration-none text-decoration-underline-hover"
      >
        <span>{translatedFields.viewMoreReplies}</span>
        {isLoading ? (
          <span
            className="text-primary link-body-emphasis link-offset-3 link-underline-opacity-0 link-underline-opacity-100-hover"
            role="status"
            aria-hidden="true"
          ></span>
        ) : (
          <i className="bi bi-chevron-right ms-1"></i>
        )}
      </a>
    </div>
  );
};
